package org.apache.ibatis.type;

import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

/**
 * 与数据库对应的类型枚举
 * 取自java jdbc规范的类型
 * @author xieqiaofu
 * Create time: 2019/10/20
 **/
public enum JdbcType {

    /**
     * 基本数据类型
     */
    BIT(Types.BIT),
    TINYINT(Types.TINYINT),
    SMALLINT(Types.SMALLINT),
    INTEGER(Types.INTEGER),
    BIGINTEGER(Types.BIGINT),

    FLOAT(Types.FLOAT),
    //不精确的双精度浮点型，8位
    REAL(Types.REAL),
    DOUBLE(Types.DOUBLE),
    //与decimal类似，38位，没有decimal精确
    NUMBERIC(Types.NUMERIC),
    DECIMAL(Types.DECIMAL),

    CHAR(Types.CHAR),
    VARCHAR(Types.VARCHAR),
    LONGVARCHAR(Types.LONGVARCHAR),
    NVARCHAR(Types.NVARCHAR), // JDK6
    NCHAR(Types.NCHAR), // JDK6
    LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6

    /**
     * 日期数据类型
     */
    DATE(Types.DATE),
    TIME(Types.TIME),
    TIMESTAMP(Types.TIMESTAMP),
    DATETIMEOFFSET(-155), // SQL Server 2008
    TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE), // JDBC 4.2 JDK8
    TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE), // JDBC 4.2 JDK8

    /**
     * 二进制数据类型
     */
    BINARY(Types.BINARY),
    VARBINARY(Types.VARBINARY),
    LONGVARBINARY(Types.LONGVARBINARY),
    //大二进制类型
    BLOB(Types.BLOB),
    //oracle中大二进制类型
    CLOB(Types.CLOB),
    NCLOB(Types.NCLOB), // JDK6

    /**
     * null类型
     */
    NULL(Types.NULL),

    /**
     * other类型
     */
    OTHER(Types.OTHER),
    UNDEFINED(Integer.MIN_VALUE + 1000),

    /**
     * 布尔类型
     */
    BOOLEAN(Types.BOOLEAN),

    /**
     * Oracle中游标类型
     */
    CURSOR(-10),

    /**
     * 文档或对象类型
     */
    STRUCT(Types.STRUCT),
    JAVA_OBJECT(Types.JAVA_OBJECT),
    REF(Types.REF),
    SQLXML(Types.SQLXML), // JDK6
    DISTINCT(Types.DISTINCT),
    DATALINK(Types.DATALINK),
    ROWID(Types.ROWID), // JDK6

    /**
     * 数组类型
     */
    ARRAY(Types.ARRAY);

    /**
     * 这个HashMap定义很精髓，可以防止java枚举类型valueOf不到值抛异常的情况，直接返回null
     */
    private static Map<Integer, JdbcType> codeLookup = new HashMap<>();

    static {
        for (JdbcType type : JdbcType.values()) {
            codeLookup.put(type.TYPE_CODE, type);
        }
    }

    public static JdbcType forCode(int code) {
        return codeLookup.get(code);
    }

    private final int TYPE_CODE;

    JdbcType(Integer code) {
        this.TYPE_CODE = code;
    }
}
